package org.daochong.spring;

import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.daochong.lang.SystemLogger;
import org.daochong.spring.util.ResourceAdaper;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.XmlWebApplicationContext;

public class DaoChongWebApplicationContext extends XmlWebApplicationContext {

	private static DaoChongWebApplicationContext INSTANCE = null;

	public static WebApplicationContext getContext() {
		return INSTANCE;
	}

	public static String DEFAULT_PATH = "/ext/spring/**/applicationContext*.xml";

	private Set<String> rs = new LinkedHashSet<String>();

	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
		if (INSTANCE == null) {
			INSTANCE = this;
		}
		String[] configLocations = getConfigLocations();
		ResourceLoader resourceLoader = reader.getResourceLoader();
		if (configLocations != null) {
			for (String configLocation : configLocations) {
				if (resourceLoader instanceof ResourcePatternResolver) {
					Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(configLocation);
					if (resources != null && resources.length > 0) {
						for (Resource r : resources) {
							rs.add(r.getFilename());
						}
					}
				} else {
					rs.add(resourceLoader.getResource(configLocation).getFilename());
				}
				reader.loadBeanDefinitions(configLocation);
			}
		}
		// Load Jar中Spring默认配置文件,如果存在同名文件，则不加载xml。如果其他文件已存在Bean定义，则不加载Bean
		List<org.daochong.lang.Resource> list = org.daochong.lang.Resource.getResources(DEFAULT_PATH);
		List<ResourceAdaper> loadRs = new ArrayList<ResourceAdaper>();
		if (list != null && list.size() > 0) {
			for (org.daochong.lang.Resource resource : list) {
				if (rs.contains(resource.getFileName()) && resource.isJar()) {
					SystemLogger.info("SpringExt", "Ignore file " + resource.getSource());
					continue;
				} else {
					loadRs.add(new ResourceAdaper(resource));
				}
			}
		}
		addExtendSpring(reader.getBeanFactory(), loadRs);
	}

	public void addExtendSpring(BeanDefinitionRegistry beanDefinitonRegistry, List<ResourceAdaper> list) {
		GenericXmlApplicationContext context = new GenericXmlApplicationContext();
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(
				(BeanDefinitionRegistry) context.getBeanFactory());
		for (ResourceAdaper resource : list) {
			try {
				beanDefinitionReader.loadBeanDefinitions(resource);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		for (String name : context.getBeanDefinitionNames()) {
			if (!beanDefinitonRegistry.containsBeanDefinition(name)) {
				beanDefinitonRegistry.registerBeanDefinition(name, context.getBeanDefinition(name));
			} else {
				SystemLogger.info("SpringExt", "Ignore Bean [" + name + "]");
			}
		}
		try {
			context.close();
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}

}
